#include "DirectInput.h"
#include "App.h"
#include "ReportError.h"

DirectInput::DirectInput()
{
	ZeroMemory(m_KeyboardState, sizeof(m_KeyboardState));
	ZeroMemory(&m_MouseState, sizeof(m_MouseState));

	if(FAILED(DirectInput8Create(g_App->GetAppInst(), DIRECTINPUT_VERSION,
		IID_IDirectInput8,(void**)&m_DInput,0)))
	{
		ReportError("Cannot Create Input Device");
		PostQuitMessage(0);
	}

	m_KeyState[0] = 0;
	m_KeyState[1] = 0;
	m_KeyState[2] = 0;
}

DirectInput::~DirectInput()
{
	if(m_DInput)
	{
		m_DInput->Release();
	}
	if(m_Keyboard)
	{
		m_Keyboard->Unacquire();
		m_Keyboard->Release();
		m_Keyboard = NULL;
	}

	if(m_Mouse)
	{
		m_Mouse->Unacquire();
		m_Mouse->Release();
		m_Mouse = NULL;
	}
}

bool DirectInput::InitKeyboard()
{
	//Identifies the default system Keyboard. m_Keyboard points to it
	if(FAILED(m_DInput->CreateDevice(GUID_SysKeyboard, &m_Keyboard,0)))
	{
		return false;
	}
	if(FAILED(m_Keyboard->SetDataFormat(&c_dfDIKeyboard)))
	{
		return false;
	}
	if(FAILED(m_Keyboard->SetCooperativeLevel(g_App->GetMainWnd(), DISCL_NONEXCLUSIVE|DISCL_FOREGROUND)))
	{
		return false;
	}
	if(FAILED(m_Keyboard->Acquire()))
	{
		return false;
	}
	return true;
}

bool DirectInput::InitMouse()
{
	if(FAILED(m_DInput->CreateDevice(GUID_SysMouse, &m_Mouse, 0)))
	{
		return false;
	}
	if(FAILED(m_Mouse->SetDataFormat(&c_dfDIMouse2)))
	{
		return false;
	}
	if(FAILED(m_Mouse->SetCooperativeLevel(g_App->GetMainWnd(), DISCL_NONEXCLUSIVE|DISCL_FOREGROUND)))
	{
		return false;
	}
	if(FAILED(m_Mouse->Acquire()))
	{
		return false;
	}
	return true;
}

void DirectInput::Update()
{
	if(m_Keyboard)
	{
		if(FAILED(m_Keyboard->GetDeviceState(sizeof(m_KeyboardState), (void**)&m_KeyboardState)))
		{
			//if the keyboard is lost, zero out the structure and attemped to re-acuire it.
			ZeroMemory(m_KeyboardState, sizeof(m_KeyboardState));
			//TODO: anotoer check?
			HRESULT hr = m_Keyboard->Acquire();
		}
	}

	if(m_Mouse)
	{
		// Poll mouse. 
		if(FAILED(m_Mouse->GetDeviceState(sizeof(DIMOUSESTATE2), (void**)&m_MouseState)) )
		{
			// Mouse lost, zero out mouse data structure.
			ZeroMemory(&m_MouseState, sizeof(m_MouseState));
			// Try to acquire for next time we poll.
			HRESULT hr = m_Mouse->Acquire(); 
		}
	}
}

bool DirectInput::KeyDown(int key)
{
	if((m_KeyboardState[key] & 0x80))
	{
		return true;
	}
	return false;
}

 bool DirectInput::KeyUp(int key)
 { 
	 return (m_KeyboardState[key] & 0x80) ? false : true; 
 }

 bool DirectInput::KeyPressed(int key)
 {
	 //check for keydown
	 if (KeyDown(key))
	 {
		 m_KeyState[key] = 1;
	 }

	 //check for key reaching the keydown state
	 if (m_KeyState[key] == 1)
	 {
		 //check for key release
		 if (KeyUp(key))
		 {
			 m_KeyState[key] = 2;
		 }
	 }

	 //check if key has been pressed and released
	 if (m_KeyState[key] == 2)
	 {
		 //reset the key status
		 m_KeyState[key] = 0;
		 return true;
	 }

	 return false;
 }

 bool DirectInput::MouseButtonDown(int button)
{
	if((m_MouseState.rgbButtons[button] & 0x80))
	{
		return true;
	}
	return false;
}

float DirectInput::MouseDX()
{
	return (float)m_MouseState.lX;
}

float DirectInput::MouseDY()
{
	return (float)m_MouseState.lY;
}

float DirectInput::MouseDZ()
{
	return (float)m_MouseState.lZ;
}